from flask import Flask, request, jsonify, g, current_app, session
from flask_jwt_extended import (
    JWTManager,
    get_jwt_identity,
    verify_jwt_in_request,
)
from flask_jwt_extended.exceptions import NoAuthorizationError, InvalidHeaderError, WrongTokenError, RevokedTokenError, \
    FreshTokenRequired

from config import Config
from extension import db
app = Flask(__name__)
app.config.from_object(Config)  # 加载配置

# 修改变量标签（默认 {{ }} → [[ ]]）
app.jinja_env.variable_start_string = '[[ '
app.jinja_env.variable_end_string = ' ]]'

# 初始化扩展
db.init_app(app)
jwt = JWTManager(app)

from routes.page import api_bp as page_bp
from routes.auth import api_bp as auth_bp
from routes.cart import api_bp as cart_bp
from routes.order import api_bp as order_bp
from routes.product import api_bp as product_bp

app.register_blueprint(page_bp)
app.register_blueprint(auth_bp)
app.register_blueprint(cart_bp)
app.register_blueprint(order_bp)
app.register_blueprint(product_bp)

@app.before_request
def verify_token():
    # 不需要拦截的路由
    exclude_routes = ['/login', '/register', '/', '/static', '/favicon.ico']
    if request.path in exclude_routes or request.path.startswith('/static'):
        return

    try:
        # 从Session中获取token
        token = session.get('token')
        if not token:
            raise NoAuthorizationError("缺少认证 Token")

        # 手动验证JWT Token
        from flask_jwt_extended import decode_token
        data = decode_token(token)

        # 获取用户身份
        user_id = data['sub']  # JWT中存储用户ID的标准字段是'sub'
        # 将用户对象存入全局对象g
        g.current_user = {
            'id': user_id
        }

    except NoAuthorizationError:
        return jsonify({'code': 401, 'msg': '缺少认证 Token'}), 401
    except InvalidHeaderError:
        return jsonify({'code': 401, 'msg': 'Token 格式不正确'}), 401
    except WrongTokenError:
        return jsonify({'code': 401, 'msg': 'Token 类型错误'}), 401
    except RevokedTokenError:
        return jsonify({'code': 401, 'msg': 'Token 已被撤销'}), 401
    except FreshTokenRequired:
        return jsonify({'code': 401, 'msg': '需要新鲜的 Token'}), 401
    except Exception as e:
        current_app.logger.error(f"Token 验证失败: {str(e)}", exc_info=True)
        return jsonify({'code': 500, 'msg': '认证服务异常'}), 500


# 开发环境自动创建表（生产环境用迁移工具）
if __name__ == '__main__':
    with app.app_context():
        if app.config['DEBUG']:
            db.create_all()
    app.run(host='0.0.0.0', port=5000, debug=app.config['DEBUG'])
